using System;

namespace Bookvar.ObjectModel.Actions
{
    /// <summary>
    /// This action deletes a topic.
    /// </summary>
    public class DeleteTopicAction : MindmapTopicActionBase
    {
        private int oldIndex;
        private Topic oldParent;
        private TopicPosition oldTopicPosition;

        /// <summary>
        /// Initializes a new instance of the <see cref="DeleteTopicAction"/> class. If the topic is floating it will 
        /// be removed from the <see cref="MindMap"/> floating topics.
        /// </summary>
        public DeleteTopicAction()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="DeleteTopicAction"/> class. If the topic is floating it will 
        /// be removed from the <paramref name="mindmap"/> floating topics.
        /// </summary>
        /// <param name="topic">The <see cref="Topic"/> to remove.</param>
        /// <param name="mindmap">The <see cref="MindMap"/> that contains the topic.</param>
        public DeleteTopicAction( Topic topic, MindMap mindmap ) : base( topic, mindmap )
        {
            Mindmap = mindmap;
        }

        /// <summary>
        /// Executes the action: deletes the topic.
        /// </summary>
        /// <exception cref="InvalidOperationException">
        /// if the <see cref="Topic"/> or the <see cref="MindMap"/> for this action is not set;
        /// </exception>
        public override void Execute()
        {
            base.Execute();

            if ( Topic.Parent != null )
            {
                DeleteConnectedTopic();
            }
            else if ( Topic.IsFloating )
            {
                DeleteFloatingTopic();
            }
        }

        /// <summary>
        /// Undoes the action.
        /// </summary>
        /// <exception cref="InvalidOperationException">
        /// if the <see cref="Topic"/> or the <see cref="MindMap"/> for this action is not set;
        /// or if Undo is called before the action is executed.
        /// </exception>
        public override void Undo()
        {
            base.Undo();

            if ( oldParent != null )
            {
                UndoDeleteConnectedTopic();
            }
            else
            {
                UndoDeleteFloatingTopic();
            }
        }

        private void DeleteConnectedTopic()
        {
            oldIndex = Topic.Parent.SubTopics.IndexOf( Topic );
            oldParent = Topic.Parent;

            Topic.Parent.SubTopics.RemoveAt( oldIndex );
            CommonDelete();
        }

        private void DeleteFloatingTopic()
        {
            oldIndex = Mindmap.FloatingTopics.IndexOf( Topic );
            Mindmap.FloatingTopics.RemoveAt( oldIndex );
            CommonDelete();
        }

        private void CommonDelete()
        {
            if ( Mindmap.TopicPositions.Contains( Topic.ID ) )
            {
                oldTopicPosition = Mindmap.TopicPositions[ Topic.ID ];
                Mindmap.TopicPositions.Remove( oldTopicPosition );
            }
        }

        private void UndoDeleteFloatingTopic()
        {
            UndoCommonDelete();
            Mindmap.FloatingTopics.Insert( oldIndex, Topic );
        }

        private void UndoDeleteConnectedTopic()
        {
            UndoCommonDelete();
            oldParent.SubTopics.Insert( oldIndex, Topic );
        }

        private void UndoCommonDelete()
        {
            if ( oldTopicPosition != null )
            {
//                // TODO: Fix Topic positions.
//                if ( !MindMap.TopicPositions.Contains( oldTopicPosition.ID ) )
//                {
                    Mindmap.TopicPositions.Add( oldTopicPosition );
//                }
            }
        }
    }
}
